﻿/*
   Original author: Dandre Jansen van Vuuren

   This wrapper code is intended to be included in the project that needs to use it.
   In other words, there is no project references made, the source file is included in the project.
   This file is not governed by the MS-PL license but carries the following disclaimer if used
   in your personal/commercial/open-source/etc project:

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
   OTHER DEALINGS IN THE SOFTWARE.
 */
using System.Text;
using System;

namespace RenewalProjects.Libraries.SharedCode
{
	/// <summary>
	/// Utility methods for working with Exceptions.
	/// </summary>
	public static class ExceptionUtilities
	{
		/// <summary>
		/// Writes out the exception and stacktrace without the inner exceptions.
		/// </summary>
		/// <param name="exception">Exception to write out</param>
		/// <returns></returns>
		public static string FormatException(Exception exception)
		{
			return FormatException(exception, 0);
		}

		/// <summary>
		/// Writes out the exception and stacktrace without the inner exceptions.
		/// </summary>
		/// <param name="exception">Exception to write out</param>
		/// <param name="indentLevel">How much the exception and stacktrace needs to be indented by tab characters</param>
		/// <returns></returns>
		public static string FormatException(Exception exception, int indentLevel)
		{
			if(indentLevel < 0)
			{
				throw new ArgumentOutOfRangeException("indentLevel", "Cannot be less than zero");
			}

			string indentStr = "";
			for(int i = 0; i < indentLevel; i++)
			{
				indentStr += "\t";
			}

			StringBuilder sb = new StringBuilder(64);

			sb.Append(indentStr);
			sb.AppendLine("[\"" + exception.Message + "\" - " + exception.GetType().FullName + "]");
			if(exception.StackTrace != null)
			{
				sb.AppendLine(exception.StackTrace.Replace("   ", indentStr + "   "));
			}

			return sb.ToString();
		}

		/// <summary>
		/// Writes out the exception and stacktrace with the inner exceptions.
		/// </summary>
		/// <param name="exception">Exception to write out</param>
		/// <returns></returns>
		public static string FormatExceptionDepth(Exception exception)
		{
			return FormatExceptionDepth(exception, 0, true);
		}

		/// <summary>
		/// Writes out the exception and stacktrace with the inner exceptions.
		/// </summary>
		/// <param name="exception">Exception to write out</param>
		/// <param name="startIndentLevel">How much the exception and stacktrace needs to be indented by tab characters to start with</param>
		/// <param name="indentLowerExceptions">Should the lower exceptions be indented additionally?</param>
		/// <returns></returns>
		public static string FormatExceptionDepth(Exception exception, int startIndentLevel, bool indentLowerExceptions)
		{
			if(startIndentLevel < 0)
			{
				throw new ArgumentOutOfRangeException("startIndentLevel", "Cannot be less than zero");
			}

			StringBuilder sb = new StringBuilder(128);
			int level = -1;
			Exception curException = exception;
			while(curException != null)
			{
				level++;

				sb.Append(FormatException(curException, indentLowerExceptions ? level +
						startIndentLevel : startIndentLevel));

				curException = curException.InnerException;
			}

			return sb.ToString();
		}
	}
}